extends layout

block headContent
	title Difficulty History

block content
	h1.h3 Difficulty History
	hr

	div.card.shadow-sm.mb-3
		div.card-body
			h3.h6.mb-0 Explanation
			hr

			ul.mb-0
				li Mining difficulty adjusts automatically every #{coinConfig.difficultyAdjustmentBlockCount.toLocaleString()} blocks.
				li The adjustment aims to maintain an average block-mining time of #{coinConfig.targetBlockTimeMinutes} minutes.
				li A growth in the difficulty indicates that the average block-mining time during the previous adjustment epoch was less than #{coinConfig.targetBlockTimeMinutes} minutes (due to more miners joining the network and 'searching' / 'mining' for blocks).
				li A drop in difficulty indicates miners have left the network so finding each block is adjusted to be 'easier' for the smaller number remaining.
				li The difficulty 'value' is a multiple of the difficulty of finding the easiest block (Block #0) - e.g. blocks in BTC mainnet epoch 308 are over 16 trillion times harder to mine than those in epoch 0. 

	div#progress-wrapper.mb-huge
		div.card.shadow-sm.mb-3
			div.card-body
				h4.h6 Loading data: 
					span(id="progress-text")
				div.progress(id="progress-bar", style="height: 7px;")
					div.progress-bar(id="data-progress", role="progressbar", aria-valuenow="0", aria-valuemin="0" ,aria-valuemax="100")


	div#main-content(style="display: none;")
		div.row
			div.col
				div.card.shadow-sm.mb-3
					div.card-body
						h3.h6.mb-0 Difficulty History
						hr

						canvas(id="graph-diff-hist")

		div.row
			div.col
				div.card.shadow-sm.mb-3
					div.card-body
						h3.h6.mb-0 Difficulty Change (clamped to ±100%)
						hr

						canvas(id="graph-diff-change")
	


block endOfBody
	script(src="/js/chart.bundle.min.js", integrity="sha384-qgOtiGNaHh9fVWUnRjyHlV39rfbDcvPPkEzL1RHvsHKbuqUqM6uybNuVnghY2z4/")
	script(src='/js/decimal.js')
	script.
		var blockCount = !{blockCount};
		
		var heights = [];
		var height = 0;
		while (height <= blockCount) {
			heights.push([height]);
			height += !{coinConfig.difficultyAdjustmentBlockCount};
		}

		$(document).ready(function() {
			loadData(heights, 1, heights.length);
		});

		function loadData(heightChunks, chunkSize, count) {
			var chunkStrs = [];
			
			for (var i = 0; i < heightChunks.length; i++) {
				var heightChunk = heightChunks[i];

				var chunkStr = "";

				for (var j = 0; j < heightChunk.length; j++) {
					if (j > 0) {
						chunkStr += ",";
					}

					chunkStr += heightChunk[j];
				}

				chunkStrs.push(chunkStr);
			}

			//alert(JSON.stringify(chunks));

			var results = [];

			var statusCallback = function(chunkIndexDone, chunkCount) {
				//console.log("Done: " + Math.min(((chunkIndexDone + 1) * chunkSize), count) + " of " + count);

				var wPercent = `${parseInt(100 * (chunkIndexDone + 1) / parseFloat(chunkCount))}%`;
				
				$("#data-progress").css("width", wPercent);
				$("#progress-text").text(`${Math.min(((chunkIndexDone + 1) * chunkSize), count).toLocaleString()} of ${count.toLocaleString()} (${wPercent})`);
			};

			var finishedCallback = function() {
				var summary = summarizeData(results);

				createGraph("graph-diff-hist", [summary.graphData], "Difficulty");

				createGraph("graph-diff-change", [summary.changeGraphData], "Difficulty Change %");

				//createGraph("graph-diff-hist-2", summary.epochChunks, "Difficulty 2");
				
				$("#main-content").show();
				$("#progress-wrapper").hide();
			};

			getData(results, chunkStrs, 0, statusCallback, finishedCallback);
		}

		function createGraph(graphId, datas, yLabelStr) {
			var datasets = [];

			for (var i = 0; i < datas.length; i++) {
				datasets.push({
					borderColor: '#007bff',
					borderWidth: 2,
					backgroundColor: 'rgba(0,0,0,0)',
					data: datas[i],
					pointRadius: 1
				});
			}

			var ctx = document.getElementById(graphId).getContext('2d');
			var graph = new Chart(ctx, {
				type: 'line',
				data: {
					datasets: datasets
				},
				options: {
					legend: { display: false },
					scales: {
						xAxes: [{
							type: 'linear',
							position: 'bottom',
							scaleLabel: {
								display: true,
								labelString: 'Difficulty Epoch'
							},
							//ticks: {
							//	stepSize: 100,
							//}
						}],
						yAxes: [{
							scaleLabel: {
								display: true,
								labelString: yLabelStr
							}
						}]
					}
				}
			});
		}

		function getData(results, chunks, chunkIndex, statusCallback, finishedCallback) {
			if (chunkIndex > chunks.length - 1) {
				finishedCallback();

				return;
			}

			var url = `/api/block-headers-by-height/${chunks[chunkIndex]}`;
			
			//console.log(url);

			$.ajax({
				url: url

			}).done(function(result) {
				for (var i = 0; i < result.length; i++) {
					results.push(result[i]);
				}

				statusCallback(chunkIndex, chunks.length);
				
				getData(results, chunks, chunkIndex + 1, statusCallback, finishedCallback);
			});
		}

		function summarizeData(raw) {
			var summary = {};
			summary.graphData = [];
			summary.changeGraphData = [];

			for (var i = 0; i < raw.length; i++) {
				summary.graphData.push({x:i, y:raw[i].difficulty});

				if (i == 0) {
					summary.changeGraphData.push({x:i, y:raw[i].difficulty});

				} else {
					var d1 = raw[i].difficulty;
					var d0 = raw[i - 1].difficulty

					var deltaPercent = 100 * (d1 / d0 - 1);
					/*if (d1 > d0) {
						// increase
						deltaPercent = 
						

					} else {
						// decrease
						deltaPercent = -100 * (1 - d1 / d0);
						
					}*/

					if (deltaPercent > 100) {
						deltaPercent = 100;
					}

					if (deltaPercent < -100) {
						deltaPercent = -100;
					}

					summary.changeGraphData.push({x:i, y:deltaPercent});
				}
			}

			/*
			var epochChunkCount = 3;
			var epochChunkSize = Math.floor(summary.graphData.length / epochChunkCount);

			summary.epochChunks = [];
			for (var i = 0; i < epochChunkCount; i++) {
				summary.epochChunks.push([]);

				var scale = summary.graphData[i * epochChunkSize].y;
				
				for (var j = 0; j < 100; j++) {
					var data = summary.graphData[i * epochChunkSize + j];

					summary.epochChunks[i].push({x:j, y:(data.y / scale)});
				}
			}*/

			return summary;
		}

